package impl

import (
	"context"
	"errors"
	admin "gitee.com/kordar/goadmin/admin/form"
	model "gitee.com/kordar/goadmin/admin/models"
	"gitee.com/kordar/goadmin/admin/service"
	"gitee.com/kordar/goadmin/admin/vo"
	"gitee.com/kordar/goadmin/reader"
	"github.com/kordar/ginsys/resource"
	"github.com/kordar/ginsys/resp"
	"github.com/kordar/gocrud"
	gocrudgorm "github.com/kordar/gocrud-gorm"

	"gorm.io/gorm"
)

type SettingServiceImpl struct {
	db *gorm.DB
	*gocrud.CommonResourceService
	dictService service.DictService
}

func NewSettingService(db *gorm.DB, dictService service.DictService) *SettingServiceImpl {
	return &SettingServiceImpl{db: db, dictService: dictService}
}

func (service SettingServiceImpl) ResourceName() string {
	return "setting"
}

func (service SettingServiceImpl) Search(body gocrud.SearchBody) gocrud.SearchVO {
	searchBody := gocrudgorm.NewGormSearchBody(body)
	db := searchBody.GormQuery(service.db, nil).Model(&model.SysSetting{})
	queryReader := reader.NewQueryReader(db, int(body.Page), int(body.PageSize))
	var settingVOS []*vo.SettingVO
	return queryReader.SearchVO(&settingVOS, nil)
}

func (service SettingServiceImpl) loopNode(source int, target int) error {
	// 0 为根节点
	if target == 0 {
		return nil
	}

	if source == target {
		return errors.New("loop")
	}

	var data []*model.SysSetting
	tx := service.db.Where("pid = ?", source).Find(&data)
	if tx.Error == nil {
		for _, item := range data {
			if item.ID == target {
				return errors.New("loop")
			}
			err := service.loopNode(item.ID, target)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (service SettingServiceImpl) Edit(body gocrud.EditorBody) error {
	return body.Updates(&model.SysSetting{}, service.db.Select("Title", "Icon", "Position", "Type", "Pid", "RouterName", "URL", "Active", "Sort"), nil)
}

func (service SettingServiceImpl) Create(body gocrud.FormBody) (interface{}, error) {
	return resource.Create(body, service.db.Select("Title", "Icon", "Position", "Type", "Pid", "RouterName", "URL", "Active", "Sort"), &admin.SettingForm{}, nil, nil)
}

func (service SettingServiceImpl) Update(body gocrud.FormBody) (interface{}, error) {
	return resource.Updates(body, service.db.Select("Title", "Icon", "Position", "Type", "Pid", "RouterName", "URL", "Active", "Sort"), &admin.SettingForm{}, nil, func(v interface{}) error {
		sysSetting := v.(*model.SysSetting)
		return service.loopNode(sysSetting.ID, sysSetting.Pid)
	})
}

func (service SettingServiceImpl) Remove(body gocrud.RemoveBody) error {
	return body.Delete(&model.SysSetting{}, service.db, nil)
}

func (service SettingServiceImpl) Configs(ctx context.Context) map[string]interface{} {
	locale := resp.GetLocale(ctx)
	return map[string]interface{}{
		"switch-state":     service.dictService.Options("configs.switch-state", locale),
		"setting-type":     service.dictService.Options("configs.setting-type", locale),
		"setting-position": service.dictService.Options("configs.setting-position", locale),
	}
}
